package com.lft.ten_commonly_used_algorithms05.greedy;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

/**
 * 贪心算法
 */
public class GreedyAlgorithm {
	public static void main(String[] args) {
		// 创建广播电台。放到Map中。
		Map<String, HashSet<String>> broadcasts = new HashMap<>();
		// 所有地区的集合。
		HashSet<String> allAreas = new HashSet<>();
		// 将各个电台放入到 broadcasts
		HashSet<String> k1 = new HashSet<>();
		k1.add("北京");
		k1.add("上海");
		k1.add("天津");
		// 加入到地区集合中。
		allAreas.addAll(k1);
		// 添加到广播中。
		broadcasts.put("K1", k1);
		HashSet<String> k2 = new HashSet<>();
		k2.add("广州");
		k2.add("北京");
		k2.add("深圳");
		allAreas.addAll(k2);
		broadcasts.put("K2", k2);
		HashSet<String> k3 = new HashSet<>();
		k3.add("成都");
		k3.add("上海");
		k3.add("杭州");
		allAreas.addAll(k3);
		broadcasts.put("K3", k3);
		HashSet<String> k4 = new HashSet<>();
		k4.add("上海");
		k4.add("天津");
		allAreas.addAll(k4);
		broadcasts.put("K4", k4);
		HashSet<String> k5 = new HashSet<>();
		k5.add("杭州");
		k5.add("大连");
		allAreas.addAll(k5);
		broadcasts.put("K5", k5);
		
		System.out.println(allAreas);
		
		System.out.println(greedyAlgorithm(broadcasts, allAreas));
		
	}
	
	/**
	 * 贪心算法方法
	 * @param broadcasts 广播电台，包含能覆盖的区域。
	 * @param allAreas   所有要覆盖的区域。
	 * @return 广播电台集合。
	 */
	public static List<String> greedyAlgorithm(Map<String, HashSet<String>> broadcasts, HashSet<String> allAreas) {
		// 创建 ArrayList 存放选择的电台集合。
		List<String> results = new ArrayList<>();
		
		// 定义一个临时集合，在遍历的过程中，存放遍历过程中的电台覆盖的地区和当前还没有覆盖的地区的交集。
		HashSet<String> tempSet = new HashSet<>();
		
		// 定义一个 maxKey，保存在一次遍历过程中，能够覆盖最多地区的地区对应的电台的key
		String maxKey = null;
		// 如果 maxKey 不为 null，则加入到 results 中。
		// 如果 allAreas 不为 0，说明还没有覆盖到所有的地区。
		while (allAreas.size() != 0) {
			// 遍历 broadcasts
			for (String key : broadcasts.keySet()) {
				HashSet<String> areasOfOnebroadcast = broadcasts.get(key);
				tempSet.addAll(areasOfOnebroadcast);
				// 获取 tempSet 和 allAreas 的交集，赋给 tempSet
				tempSet.retainAll(allAreas);
				// 如果当前这个集合包含的未覆盖地区的数量，比 maxKey 指向的集合地区还多。【贪心算法核心】
				if (tempSet.size() > 0 && (maxKey == null || tempSet.size() > broadcasts.get(maxKey).size())) {
					// 重置 maxKey
					maxKey = key;
				}
				// 每次循环要清空。
				tempSet.clear();
			}
			// maxKey != null 就应该将 maxKey 加入到 results 中。
			if (maxKey != null) {
				results.add(maxKey);
				// 将 maxKey 指向的广播电台覆盖的地区，从 allAreas 中去掉。
				allAreas.removeAll(broadcasts.get(maxKey));
			}
			// 重置 maxKey。
			maxKey = null;
		}
		return results;
	}
}
